# main.py
# 版权信息：归玉师人事处

import sys
import pandas as pd
import random
from PySide6.QtWidgets import (
    QApplication, QMainWindow, QMenuBar, QMenu, QWidget, QVBoxLayout,
    QHBoxLayout, QLabel, QPushButton, QLineEdit, QFileDialog,
    QTreeWidget, QTreeWidgetItem, QTableWidget, QTableWidgetItem,
    QHeaderView, QDialog, QFormLayout, QInputDialog, QMessageBox
)
from PySide6.QtCore import Qt
import sqlite3

from qt_material import apply_stylesheet


class RecruitmentSystem(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("招聘管理系统")

        # 数据库文件
        self.db_file = "recruitment.db"
        self.conn = sqlite3.connect(self.db_file)
        self.init_db()

        # 缓存数据
        self.hiring_plans = []
        self.candidates = []

        # 加载数据
        self.load_hiring_plans()
        self.load_candidates()

        # 创建菜单栏
        self.create_menu()

        # 创建主界面
        self.tabs = QWidget()
        self.setCentralWidget(self.tabs)
        self.layout = QVBoxLayout()
        self.tabs.setLayout(self.layout)

        # 创建选项卡
        self.create_tabs()
        
        # 添加版权信息标签
        self.add_copyright_info()

    def closeEvent(self, event):
        """关闭窗口时关闭数据库连接"""
        self.conn.close()
        event.accept()

    def init_db(self):
        """初始化数据库表结构"""
        with self.conn:
            # 招聘计划表
            self.conn.execute('''CREATE TABLE IF NOT EXISTS hiring_plans (
                                id INTEGER PRIMARY KEY AUTOINCREMENT,
                                name TEXT NOT NULL,
                                required_count INTEGER,
                                education_level TEXT,
                                major TEXT,
                                employment_type TEXT,
                                job_level TEXT)''')

            # 考生信息表
            self.conn.execute('''CREATE TABLE IF NOT EXISTS candidates (
                                id INTEGER PRIMARY KEY AUTOINCREMENT,
                                job_id INTEGER,
                                name TEXT NOT NULL,
                                gender TEXT,
                                check_in_status TEXT DEFAULT '未签到',
                                written_score REAL DEFAULT 0,
                                interview_score REAL DEFAULT 0,
                                FOREIGN KEY(job_id) REFERENCES hiring_plans(id))''')

    def load_hiring_plans(self):
        """从数据库加载招聘计划"""
        with self.conn:
            cursor = self.conn.cursor()
            cursor.execute("SELECT * FROM hiring_plans")
            rows = cursor.fetchall()
            self.hiring_plans = [dict(zip(
                ['id', 'name', 'required_count', 'education_level', 'major', 'employment_type', 'job_level'],
                row)) for row in rows]

    def load_candidates(self):
        """从数据库加载考生信息"""
        with self.conn:
            cursor = self.conn.cursor()
            cursor.execute("SELECT * FROM candidates")
            rows = cursor.fetchall()
            self.candidates = [dict(zip(
                ['id', 'job_id', 'name', 'gender', 'check_in_status', 'written_score', 'interview_score'],
                row)) for row in rows]

    def create_menu(self):
        """创建菜单栏"""
        menubar = self.menuBar()

        # 文件菜单
        file_menu = menubar.addMenu("文件")
        file_menu.addAction("导入招聘计划", self.import_hiring_plan)
        file_menu.addAction("导出招聘计划", self.export_hiring_plan)
        file_menu.addAction("导入考生信息", self.import_candidates)
        file_menu.addAction("导出排名", self.export_ranking)

        # 工具菜单
        tool_menu = menubar.addMenu("工具")
        tool_menu.addAction("生成席位牌", self.generate_seat_signs)
        tool_menu.addAction("生成抽签", self.generate_lots)

    def create_tabs(self):
        """创建选项卡界面"""
        from PySide6.QtWidgets import QTabWidget
        tab_widget = QTabWidget()
        self.layout.addWidget(tab_widget)

        # 招聘计划页面
        hiring_frame = QWidget()
        self.create_hiring_plan_ui(hiring_frame)
        tab_widget.addTab(hiring_frame, "招聘计划")

        # 考生签到页面
        checkin_frame = QWidget()
        self.create_checkin_ui(checkin_frame)
        tab_widget.addTab(checkin_frame, "考生签到")

        # 成绩录入页面
        score_frame = QWidget()
        self.create_score_input_ui(score_frame)
        tab_widget.addTab(score_frame, "录入成绩")

        # 实时排名页面
        rank_frame = QWidget()
        self.create_rank_display(rank_frame)
        tab_widget.addTab(rank_frame, "实时排名")

    def add_copyright_info(self):
        """添加版权信息显示"""
        copyright_label = QLabel("© 归玉师人事处")
        copyright_label.setAlignment(Qt.AlignCenter)
        self.layout.addWidget(copyright_label)
        # 添加弹性空间，使版权信息靠底部
        self.layout.addStretch()

    def create_hiring_plan_ui(self, parent):
        """招聘计划界面"""
        layout = QVBoxLayout(parent)

        self.plan_tree = QTreeWidget()
        self.plan_tree.setHeaderLabels(["序号", "岗位名称", "招聘人数", "学历学位", "专业", "用人方式", "岗位等级"])
        self.plan_tree.itemDoubleClicked.connect(self.edit_position)
        layout.addWidget(self.plan_tree)

        btn_layout = QHBoxLayout()
        add_btn = QPushButton("添加岗位")
        add_btn.clicked.connect(self.add_position)
        btn_layout.addWidget(add_btn)
        layout.addLayout(btn_layout)

        self.refresh_plan_tree()

    def create_checkin_ui(self, parent):
        """考生签到界面"""
        layout = QVBoxLayout(parent)

        self.checkin_tree = QTreeWidget()
        self.checkin_tree.setHeaderLabels(["报考岗位", "姓名", "性别", "签到状态"])
        layout.addWidget(self.checkin_tree)

        btn_layout = QHBoxLayout()
        import_btn = QPushButton("导入考生信息")
        generate_btn = QPushButton("生成签到表")
        import_btn.clicked.connect(self.import_candidates)
        generate_btn.clicked.connect(self.generate_checkin_sheet)
        btn_layout.addWidget(import_btn)
        btn_layout.addWidget(generate_btn)
        layout.addLayout(btn_layout)

        self.refresh_checkin_tree()

    def create_score_input_ui(self, parent):
        """成绩录入界面"""
        layout = QVBoxLayout(parent)

        self.score_table = QTableWidget()
        self.score_table.setColumnCount(4)
        self.score_table.setHorizontalHeaderLabels(["岗位名称", "考生姓名", "笔试成绩", "面试成绩"])
        self.score_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.score_table.cellChanged.connect(self.on_score_changed)
        layout.addWidget(self.score_table)

        filter_layout = QHBoxLayout()
        self.job_filter = QLineEdit()
        self.name_filter = QLineEdit()
        filter_btn = QPushButton("过滤")
        filter_btn.clicked.connect(self.filter_candidates)
        filter_layout.addWidget(QLabel("岗位名称:"))
        filter_layout.addWidget(self.job_filter)
        filter_layout.addWidget(QLabel("考生姓名:"))
        filter_layout.addWidget(self.name_filter)
        filter_layout.addWidget(filter_btn)
        layout.addLayout(filter_layout)

        self.refresh_score_table()

    def create_rank_display(self, parent):
        """实时排名界面"""
        layout = QVBoxLayout(parent)

        self.rank_table = QTableWidget()
        self.rank_table.setColumnCount(9)
        self.rank_table.setHorizontalHeaderLabels([
            "序号", "岗位序号", "岗位名称", "招聘人数", "考生姓名", "性别", "笔试成绩", "面试成绩", "排名"
        ])
        self.rank_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        layout.addWidget(self.rank_table)

        update_btn = QPushButton("更新排名")
        export_btn = QPushButton("导出排名")
        update_btn.clicked.connect(self.update_ranking)
        export_btn.clicked.connect(self.export_ranking)
        layout.addWidget(update_btn)
        layout.addWidget(export_btn)

        self.update_ranking()

    # === 招聘计划操作 ===
    def add_position(self):
        text, ok = QInputDialog.getText(self, "添加岗位", "请输入岗位名称:")
        if ok and text:
            with self.conn:
                self.conn.execute(
                    "INSERT INTO hiring_plans (name, required_count, education_level, major, employment_type, job_level) VALUES (?, ?, ?, ?, ?, ?)",
                    (text, 1, "本科及以上", "不限", "合同制", "初级")
                )
            self.load_hiring_plans()
            self.refresh_plan_tree()

    def edit_position(self, item, column):
        if not item:
            return
        plan_id = int(item.text(0))
        plan = next((p for p in self.hiring_plans if p['id'] == plan_id), None)
        if plan:
            new_name, ok = QInputDialog.getText(self, "修改岗位", "岗位名称:", text=plan['name'])
            if ok and new_name:
                with self.conn:
                    self.conn.execute("UPDATE hiring_plans SET name = ? WHERE id = ?", (new_name, plan_id))
                self.load_hiring_plans()
                self.refresh_plan_tree()

    def refresh_plan_tree(self):
        self.plan_tree.clear()
        for plan in self.hiring_plans:
            item = QTreeWidgetItem([
                str(plan['id']),
                plan['name'],
                str(plan['required_count']),
                plan['education_level'],
                plan['major'],
                plan['employment_type'],
                plan['job_level']
            ])
            self.plan_tree.addTopLevelItem(item)

    # === 考生信息操作 ===
    def import_candidates(self):
        file_path, _ = QFileDialog.getOpenFileName(self, "导入考生信息", "", "Excel Files (*.xlsx *.xls)")
        if file_path:
            try:
                df = pd.read_excel(file_path)
                with self.conn:
                    for _, row in df.iterrows():
                        job_id = row.get('报考岗位', 1)
                        name = row.get('姓名', '未知')
                        gender = row.get('性别', '未知')
                        self.conn.execute(
                            "INSERT OR IGNORE INTO candidates (job_id, name, gender) VALUES (?, ?, ?)",
                            (job_id, name, gender)
                        )
                self.load_candidates()
                self.refresh_checkin_tree()
                self.refresh_score_table()
                QMessageBox.information(self, "成功", f"成功导入 {len(df)} 名考生")
            except Exception as e:
                QMessageBox.critical(self, "错误", f"导入失败：{str(e)}")

    def generate_checkin_sheet(self):
        df = pd.DataFrame(self.candidates)
        if df.empty:
            QMessageBox.warning(self, "提示", "暂无考生信息")
            return
        file_path, _ = QFileDialog.getSaveFileName(self, "生成签到表", "", "Excel Files (*.xlsx)")
        if file_path:
            df.to_excel(file_path, index=False)
            QMessageBox.information(self, "成功", f"签到表已保存至：{file_path}")

    def refresh_checkin_tree(self):
        self.checkin_tree.clear()
        for candidate in self.candidates:
            job_name = next((p['name'] for p in self.hiring_plans if p['id'] == candidate['job_id']), '未知岗位')
            item = QTreeWidgetItem([
                job_name,
                candidate['name'],
                candidate['gender'],
                candidate['check_in_status']
            ])
            self.checkin_tree.addTopLevelItem(item)

    # === 成绩录入 ===
    def refresh_score_table(self):
        filtered = self.candidates
        job_filter = self.job_filter.text().strip()
        name_filter = self.name_filter.text().strip()

        if job_filter:
            filtered = [c for c in filtered if job_filter in str(c['job_id'])]
        if name_filter:
            filtered = [c for c in filtered if name_filter in c['name']]

        self.score_table.setRowCount(len(filtered))
        for i, c in enumerate(filtered):
            job_name = next((p['name'] for p in self.hiring_plans if p['id'] == c['job_id']), '未知')
            self.score_table.setItem(i, 0, QTableWidgetItem(job_name))
            self.score_table.setItem(i, 1, QTableWidgetItem(c['name']))
            self.score_table.setItem(i, 2, QTableWidgetItem(str(c['written_score'])))
            self.score_table.setItem(i, 3, QTableWidgetItem(str(c['interview_score'])))

    def filter_candidates(self):
        self.refresh_score_table()

    def on_score_changed(self, row, col):
        if col < 2:
            return
        try:
            value = float(self.score_table.item(row, col).text())
            candidate_id = self.candidates[row]['id']
            field = 'written_score' if col == 2 else 'interview_score'
            with self.conn:
                self.conn.execute(f"UPDATE candidates SET {field} = ? WHERE id = ?", (value, candidate_id))
            self.load_candidates()  # 同步内存数据
        except (ValueError, IndexError):
            pass

    # === 实时排名 ===
    def update_ranking(self):
        ranking_data = []
        for candidate in self.candidates:
            job = next((j for j in self.hiring_plans if j['id'] == candidate['job_id']), None)
            if job:
                job_candidates = [c for c in self.candidates if c['job_id'] == candidate['job_id']]
                job_candidates.sort(key=lambda x: (-x['interview_score'], -x['written_score']))
                for i, c in enumerate(job_candidates):
                    if i > 0 and c['interview_score'] == job_candidates[i-1]['interview_score']:
                        c['rank'] = job_candidates[i-1]['rank']
                    else:
                        c['rank'] = i + 1
                ranking_data.extend(job_candidates)

        self.rank_table.setRowCount(len(ranking_data))
        for idx, data in enumerate(ranking_data):
            job_info = next((j for j in self.hiring_plans if j['id'] == data['job_id']), {})
            row = [
                str(idx + 1),
                str(data['job_id']),
                job_info.get('name', ''),
                str(job_info.get('required_count', '')),
                data['name'],
                data['gender'],
                str(data['written_score']),
                str(data['interview_score']),
                str(data['rank'])
            ]
            for col, val in enumerate(row):
                self.rank_table.setItem(idx, col, QTableWidgetItem(val))

    def export_ranking(self):
        columns = [self.rank_table.horizontalHeaderItem(col).text() for col in range(self.rank_table.columnCount())]
        data = []
        for row in range(self.rank_table.rowCount()):
            data.append([self.rank_table.item(row, col).text() for col in range(self.rank_table.columnCount())])
        if not data:
            QMessageBox.warning(self, "提示", "暂无排名数据")
            return
        df = pd.DataFrame(data, columns=columns)
        file_path, _ = QFileDialog.getSaveFileName(self, "导出排名", "", "Excel Files (*.xlsx)")
        if file_path:
            df.to_excel(file_path, index=False)
            QMessageBox.information(self, "成功", f"排名已导出至：{file_path}")

    # === 工具功能 ===
    def generate_seat_signs(self):
        names = [c['name'] for c in self.candidates]
        if not names:
            QMessageBox.warning(self, "提示", "暂无考生信息")
            return
        file_path, _ = QFileDialog.getSaveFileName(self, "生成席位牌", "", "Excel Files (*.xlsx)")
        if file_path:
            df = pd.DataFrame({"席位": names})
            df.to_excel(file_path, index=False)
            QMessageBox.information(self, "成功", f"席位牌已生成：{file_path}")

    def generate_lots(self):
        dialog = QDialog(self)
        dialog.setWindowTitle("生成抽签")
        layout = QFormLayout(dialog)

        title_input = QLineEdit()
        range_input = QLineEdit("1-20")
        layout.addRow("标题:", title_input)
        layout.addRow("签号范围 (起始-结束):", range_input)

        def generate():
            title = title_input.text()
            range_str = range_input.text()
            try:
                start, end = map(int, range_str.split('-'))
                if start > end:
                    raise ValueError("起始号不能大于结束号")
                sign_numbers = list(range(start, end + 1))
                random.shuffle(sign_numbers)
                df = pd.DataFrame({title or "签号": sign_numbers})
                file_path, _ = QFileDialog.getSaveFileName(dialog, "保存抽签", "", "Excel Files (*.xlsx)")
                if file_path:
                    df.to_excel(file_path, index=False)
                    dialog.accept()
                    QMessageBox.information(self, "成功", "抽签已生成并保存")
            except Exception as e:
                QMessageBox.critical(dialog, "错误", f"生成失败：{str(e)}")

        generate_btn = QPushButton("生成抽签")
        generate_btn.clicked.connect(generate)
        layout.addRow(generate_btn)
        dialog.exec()

    # === 文件导入导出 ===
    def import_hiring_plan(self):
        file_path, _ = QFileDialog.getOpenFileName(self, "导入招聘计划", "", "Excel Files (*.xlsx *.xls)")
        if file_path:
            try:
                df = pd.read_excel(file_path)
                with self.conn:
                    for _, row in df.iterrows():
                        self.conn.execute(
                            "INSERT OR IGNORE INTO hiring_plans (name, required_count, education_level, major, employment_type, job_level) VALUES (?, ?, ?, ?, ?, ?)",
                            (row['岗位名称'], row['招聘人数'], row['学历学位'], row['专业'], row['用人方式'], row['岗位等级'])
                        )
                self.load_hiring_plans()
                self.refresh_plan_tree()
                QMessageBox.information(self, "成功", "招聘计划导入成功")
            except Exception as e:
                QMessageBox.critical(self, "错误", f"导入失败：{str(e)}")

    def export_hiring_plan(self):
        df = pd.DataFrame(self.hiring_plans)
        if df.empty:
            QMessageBox.warning(self, "提示", "暂无招聘计划")
            return
        file_path, _ = QFileDialog.getSaveFileName(self, "导出招聘计划", "", "Excel Files (*.xlsx)")
        if file_path:
            df.to_excel(file_path, index=False)
            QMessageBox.information(self, "成功", f"招聘计划已导出至：{file_path}")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = RecruitmentSystem()
    apply_stylesheet(app, theme='dark_lightgreen.xml', invert_secondary=False)
    window.show()
    sys.exit(app.exec())